package com.example.ezexcel.util;

import com.example.ezexcel.enumerator.ServiceCode;
import com.example.ezexcel.ex.ServiceException;
import com.example.ezexcel.pojo.entity.QuestionData;
import com.example.ezexcel.pojo.vo.*;
import freemarker.core.XMLOutputFormat;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Select;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Value;


import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
public class WordUtil {
    private static String resultPath = "D:/excelFile/";

    //配置信息,代码本身写的还是很可读的,就不过多注解了
    private static Configuration configuration = null;
    // 这里注意的是利用WordUtils的类加载器动态获得模板文件的位置


//    private static final String templateFolder = WordUtil.class.getClassLoader().getResource("../../../../templates").getPath();
    //过滤掉/
//    private static final String templateFolder = "F:\\project\\ezexcel\\src\\main\\resources\\templates";

    private static final String templateFolder = "D:\\excelToWord\\file";

    static {
        configuration = new Configuration(Configuration.VERSION_2_3_30);
        configuration.setDefaultEncoding("utf-8");
        configuration.setOutputFormat(XMLOutputFormat.INSTANCE);
        try {
            System.out.println(templateFolder);
            configuration.setDirectoryForTemplateLoading(new File(templateFolder));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //案例题
    public static void convertCase(FreemarkerData freemarkerData, List<QuestionData> questionDataList) {
        //遍历questionDataList，获取每个题目的选项及数量赋值给FreemarkerData
        for (QuestionData questionData : questionDataList) {
            if (freemarkerData.getCaseTopic() == null) {
                List<SelectCaseVO> selectCaseVOS = new ArrayList<>();
                freemarkerData.setCaseTopic(selectCaseVOS);
            }
            //加入索引
            if (freemarkerData.getCaseNum() == null) {
                freemarkerData.setCaseNum(0);
            }
            if (questionData.getQuestionContent() == null) {
                throw new ServiceException(ServiceCode.OPERATION_FAILED, "请检查工种为【"+questionData.getWorkType()+"】，" +
                        "序号为【"+questionData.getNum()+"】的是否有题目内容");
            }
            if (freemarkerData.getQuestionBankName() == null) {
                freemarkerData.setQuestionBankName(new ArrayList<>());
            }
            //获取图片地址questionData.getQuestionContent()以$$分割如果存在图片否则不存在
            String[] questionContent = questionData.getQuestionContent().split("\\$;\\$");

            //如果questionOptions.length不等于4，跳过
            if (questionContent.length == 1) {
                throw new ServiceException(ServiceCode.OPERATION_FAILED, "请检查工种为【"+questionData.getWorkType()+"】，" +
                        "序号为【"+questionData.getNum()+"】的题目内容是否有误");
            }
            SelectCaseVO selectCaseVO = new SelectCaseVO();
            selectCaseVO.setNumber(freemarkerData.getCaseNum() + 1);
            selectCaseVO.setAnswer(questionData.getQuestionAnswer());
            selectCaseVO.setWorkType(questionData.getWorkType());
            selectCaseVO.setReferenceSource(questionData.getReferenceSource());
            for (String msg : questionContent) {
                //第一个1是题目内容，后面都是每个小点
                if (msg.equals(questionContent[0])) {
                    selectCaseVO.setTitle(msg);
                    continue;
                }
                if (selectCaseVO.getQuestionContentList() == null) {
                    List<String> QuestionConten = new ArrayList<>();
                    selectCaseVO.setQuestionContentList(QuestionConten);
                }
                selectCaseVO.getQuestionContentList().add(msg);
            }
            freemarkerData.getCaseTopic().add(selectCaseVO);
            //如果freemarkerData.getQuestionBankName()不包含questionData.getQuestionBankName()则加入
            if (!freemarkerData.getQuestionBankName().contains(questionData.getQuestionBankName())) {
                freemarkerData.getQuestionBankName().add(questionData.getQuestionBankName());
            }
            freemarkerData.setCaseNum(freemarkerData.getCaseNum() + 1);
            //拼接questionData.getNum()+，
            if (freemarkerData.getCaseNumStr() == null) {
                freemarkerData.setCaseNumStr(questionData.getNum() + ",");
            } else {
                freemarkerData.setCaseNumStr(freemarkerData.getCaseNumStr() + questionData.getNum() + ",");
            }

            System.err.println(freemarkerData.getCaseTopic());
        }
        log.info("getCaseNumStr:{}", freemarkerData.getCaseNumStr());
    }


    //计算题
    public static void convertCalculation(FreemarkerData freemarkerData, List<QuestionData> questionDataList) {
        //遍历questionDataList，获取每个题目的选项及数量赋值给FreemarkerData
        for (QuestionData questionData : questionDataList) {
            if (freemarkerData.getCalculation() == null) {
                List<SelectCalculationVO> selectCalculationVOList = new ArrayList<>();
                freemarkerData.setCalculation(selectCalculationVOList);
            }
            //加入索引
            if (freemarkerData.getCalculationNum() == null) {
                freemarkerData.setCalculationNum(0);
            }
            if (questionData.getQuestionContent() == null) {
                throw new ServiceException(ServiceCode.OPERATION_FAILED, "请检查工种为【"+questionData.getWorkType()+"】，" +
                        "序号为【"+questionData.getNum()+"】的是否有题目内容");
            }
            if (freemarkerData.getQuestionBankName() == null) {
                freemarkerData.setQuestionBankName(new ArrayList<>());
            }
            //获取图片地址questionData.getQuestionContent()以$$分割如果存在图片否则不存在
            String[] questionContent = questionData.getQuestionContent().split("\\$;\\$");

            //如果questionOptions.length不等于4，跳过这个题目
            if (questionContent.length != 2) {
                throw new ServiceException(ServiceCode.OPERATION_FAILED, "请检查工种为【"+questionData.getWorkType()+"】，" +
                        "序号为【"+questionData.getNum()+"】的题目选项是否有图片地址");
            }
            questionData.setQuestionContent(questionContent[0]);
            log.error("================================================:{}", questionContent[1]);
            SelectCalculationVO selectCalculationVO = new SelectCalculationVO();
            selectCalculationVO.setNumber(freemarkerData.getCalculationNum() + 1);
            selectCalculationVO.setTitle(questionData.getQuestionContent());
            selectCalculationVO.setImgBase64(Tools.getBase64ByPath(questionContent[1].replace("\\", "\\\\")));
            selectCalculationVO.setAnswer(questionData.getQuestionAnswer());
            selectCalculationVO.setEvaluationDimension(questionData.getEvaluationDimension());
            selectCalculationVO.setEvaluationModuleName(questionData.getEvaluationModuleName());
            selectCalculationVO.setKnowledgeSkillPointName(questionData.getKnowledgeSkillPointName());
            selectCalculationVO.setEvaluationLevel(questionData.getEvaluationLevel());
            selectCalculationVO.setDifficultyLevel(questionData.getDifficultyLevel());

//            log.error("================================================:{}", selectCalculationVO.getImgBase64());
            freemarkerData.getCalculation().add(selectCalculationVO);
            //如果freemarkerData.getQuestionBankName()不包含questionData.getQuestionBankName()则加入
            if (!freemarkerData.getQuestionBankName().contains(questionData.getQuestionBankName())) {
                freemarkerData.getQuestionBankName().add(questionData.getQuestionBankName());
            }
            freemarkerData.setCalculationNum(freemarkerData.getCalculationNum() + 1);
            //拼接questionData.getNum()+，
            if (freemarkerData.getCalculationNumStr() == null) {
                freemarkerData.setCalculationNumStr(questionData.getNum() + ",");
            } else {
                freemarkerData.setCalculationNumStr(freemarkerData.getCalculationNumStr() + questionData.getNum() + ",");
            }

        }
        log.info("getCalculationNumStr:{}", freemarkerData.getCalculationNumStr());


    }


    //简答题
    public static void convertShortAnswer (FreemarkerData freemarkerData, List<QuestionData> questionDataList) {
        //遍历questionDataList，获取每个题目的选项及数量赋值给FreemarkerData
        for (QuestionData questionData : questionDataList) {
            if (freemarkerData.getShortAnswer() == null) {
                List<SelectJudgmentOrShortAnswerVO> selectTopicsVOList = new ArrayList<>();
                freemarkerData.setShortAnswer(selectTopicsVOList);
            }
            //加入索引
            if (freemarkerData.getShortAnswerNum() == null) {
                freemarkerData.setShortAnswerNum(0);
            }
            if (freemarkerData.getQuestionBankName() == null) {
                freemarkerData.setQuestionBankName(new ArrayList<>());
            }
            SelectJudgmentOrShortAnswerVO selectJudgmentOrShortAnswerVO = new SelectJudgmentOrShortAnswerVO();
            selectJudgmentOrShortAnswerVO.setNumber(freemarkerData.getShortAnswerNum() + 1);
            selectJudgmentOrShortAnswerVO.setTitle(questionData.getQuestionContent());
            selectJudgmentOrShortAnswerVO.setAnswer(questionData.getQuestionAnswer());
            freemarkerData.getShortAnswer().add(selectJudgmentOrShortAnswerVO);
            //如果freemarkerData.getQuestionBankName()不包含questionData.getQuestionBankName()则加入
            if (!freemarkerData.getQuestionBankName().contains(questionData.getQuestionBankName())) {
                freemarkerData.getQuestionBankName().add(questionData.getQuestionBankName());
            }
            freemarkerData.setShortAnswerNum(freemarkerData.getShortAnswerNum() + 1);
            //拼接questionData.getNum()+，
            if (freemarkerData.getShortAnswerNumStr() == null) {
                freemarkerData.setShortAnswerNumStr(questionData.getNum() + ",");
            } else {
                freemarkerData.setShortAnswerNumStr(freemarkerData.getShortAnswerNumStr() + questionData.getNum() + ",");
            }
        }
        log.info("getShortAnswerNumStr:{}", freemarkerData.getShortAnswerNumStr());
    }

    //判断题
    public static void convertJudgement (FreemarkerData freemarkerData, List<QuestionData> questionDataList) {
        //遍历questionDataList，获取每个题目的选项及数量赋值给FreemarkerData
        for (QuestionData questionData : questionDataList) {
            if (freemarkerData.getJudgment() == null) {
                List<SelectJudgmentOrShortAnswerVO> selectTopicsVOList = new ArrayList<>();
                freemarkerData.setJudgment(selectTopicsVOList);
            }
            //加入索引
            if (freemarkerData.getJudgmentNum() == null) {
                freemarkerData.setJudgmentNum(0);
            }
            if (freemarkerData.getQuestionBankName() == null) {
                freemarkerData.setQuestionBankName(new ArrayList<>());
            }
            SelectJudgmentOrShortAnswerVO selectJudgmentOrShortAnswerVO = new SelectJudgmentOrShortAnswerVO();
            selectJudgmentOrShortAnswerVO.setNumber(freemarkerData.getJudgmentNum() + 1);
            selectJudgmentOrShortAnswerVO.setTitle(questionData.getQuestionContent());
            selectJudgmentOrShortAnswerVO.setAnswer(questionData.getQuestionAnswer());
            freemarkerData.getJudgment().add(selectJudgmentOrShortAnswerVO);
            //如果freemarkerData.getQuestionBankName()不包含questionData.getQuestionBankName()则加入
            if (!freemarkerData.getQuestionBankName().contains(questionData.getQuestionBankName())) {
                freemarkerData.getQuestionBankName().add(questionData.getQuestionBankName());
            }
            freemarkerData.setJudgmentNum(freemarkerData.getJudgmentNum() + 1);
            //拼接questionData.getNum()+，
            if (freemarkerData.getJudgmentNumStr() == null) {
                freemarkerData.setJudgmentNumStr(questionData.getNum() + ",");
            } else {
                freemarkerData.setJudgmentNumStr(freemarkerData.getJudgmentNumStr() + questionData.getNum() + ",");
            }
        }
        log.info("getJudgmentNumStr:{}", freemarkerData.getJudgmentNumStr());
    }
    //多选题
    public static void convertMultipleChoice (FreemarkerData freemarkerData, List<QuestionData> questionDataList) {
        //遍历questionDataList，获取每个题目的选项及数量赋值给FreemarkerData
        for (QuestionData questionData : questionDataList) {
            if (freemarkerData.getMultipleChoice() == null) {
                List<SelectTopicsVO> selectTopicsVOList = new ArrayList<>();
                freemarkerData.setMultipleChoice(selectTopicsVOList);
            }
            //加入索引
            if (freemarkerData.getMultipleChoiceNum() == null) {
                freemarkerData.setMultipleChoiceNum(0);
            }
            if (freemarkerData.getQuestionBankName() == null) {
                freemarkerData.setQuestionBankName(new ArrayList<>());
            }
            SelectTopicsVO selectTopicsVO = new SelectTopicsVO();
            selectTopicsVO.setNumber(freemarkerData.getMultipleChoiceNum() + 1);
            selectTopicsVO.setTitle(questionData.getQuestionContent());
            selectTopicsVO.setAnswer(questionData.getQuestionAnswer());
            //questionData.getQuestionOptions()按照$$分割成数组从a到d分别赋值给selectTopicsVO
            //可能questionData.getQuestionOptions()没有$$，报异常
            log.info("题目内容为：{}", questionData);
            log.info("questionOptions:{}", questionData.getQuestionOptions());
            if (questionData.getQuestionOptions() == null) {
                throw new ServiceException(ServiceCode.OPERATION_FAILED, "请检查工种为【"+questionData.getWorkType()+"】，序号为【"+questionData.getNum()+"】的题目是否有选项");
            }
            String[] questionOptions = questionData.getQuestionOptions().split("\\$;\\$");

            //如果questionOptions.length不等于4，跳过这个题目
            if (questionOptions.length != 4) {
                throw new ServiceException(ServiceCode.OPERATION_FAILED, "请检查工种为【"+questionData.getWorkType()+"】，序号为【"+questionData.getNum()+"】的题目选项是否有$$");
            }


            selectTopicsVO.setOptionA(questionOptions[0]);
            selectTopicsVO.setOptionB(questionOptions[1]);
            selectTopicsVO.setOptionC(questionOptions[2]);
            selectTopicsVO.setOptionD(questionOptions[3]);
            //如果freemarkerData.getQuestionBankName()不包含questionData.getQuestionBankName()则加入
            if (!freemarkerData.getQuestionBankName().contains(questionData.getQuestionBankName())) {
                freemarkerData.getQuestionBankName().add(questionData.getQuestionBankName());
            }
            freemarkerData.getMultipleChoice().add(selectTopicsVO);
            freemarkerData.setMultipleChoiceNum(freemarkerData.getMultipleChoiceNum() + 1);
            //拼接questionData.getNum()+，
            if (freemarkerData.getMultipleChoiceNumStr() == null) {
                freemarkerData.setMultipleChoiceNumStr(questionData.getNum() + ",");
            } else {
                freemarkerData.setMultipleChoiceNumStr(freemarkerData.getMultipleChoiceNumStr() + questionData.getNum() + ",");
            }
        }
        log.info("getMultipleChoiceNumStr:{}", freemarkerData.getMultipleChoiceNumStr());
    }
    //单选题
    public static void convertSingleChoice (FreemarkerData freemarkerData, List<QuestionData> questionDataList) {
        //遍历questionDataList，获取每个题目的选项及数量赋值给FreemarkerData
        for (QuestionData questionData : questionDataList) {
            if (freemarkerData.getSingleChoice() == null) {
                List<SelectTopicsVO> selectTopicsVOList = new ArrayList<>();
                freemarkerData.setSingleChoice(selectTopicsVOList);
            }
            //加入索引
            if (freemarkerData.getSingleChoiceNum() == null) {
                freemarkerData.setSingleChoiceNum(0);
            }
            if (freemarkerData.getQuestionBankName() == null) {
                freemarkerData.setQuestionBankName(new ArrayList<>());
            }
            SelectTopicsVO selectTopicsVO = new SelectTopicsVO();
            selectTopicsVO.setNumber(freemarkerData.getSingleChoiceNum() + 1);
            selectTopicsVO.setTitle(questionData.getQuestionContent());
            //questionData.getQuestionOptions()按照$$分割成数组从a到d分别赋值给selectTopicsVO
            log.info("题目内容为：{}", questionData);
            log.info("questionOptions:{}", questionData.getQuestionOptions());
            if (questionData.getQuestionOptions() == null) {
                throw new ServiceException(ServiceCode.OPERATION_FAILED, "请检查工种为【"+questionData.getWorkType()+"】，序号为【"+questionData.getNum()+"】的题目是否有选项");
            }
            String[] questionOptions = questionData.getQuestionOptions().split("\\$;\\$");

            //如果questionOptions.length不等于4，跳过这个题目
            if (questionOptions.length != 4) {
                throw new ServiceException(ServiceCode.OPERATION_FAILED, "请检查工种为【"+questionData.getWorkType()+"】，序号为【"+questionData.getNum()+"】的题目选项是否有$$");
            }
            selectTopicsVO.setOptionA(questionOptions[0]);
            selectTopicsVO.setOptionB(questionOptions[1]);
            selectTopicsVO.setOptionC(questionOptions[2]);
            selectTopicsVO.setOptionD(questionOptions[3]);
            selectTopicsVO.setAnswer(questionData.getQuestionAnswer());
            freemarkerData.getSingleChoice().add(selectTopicsVO);

            //如果freemarkerData.getQuestionBankName()不包含questionData.getQuestionBankName()则加入
            if (!freemarkerData.getQuestionBankName().contains(questionData.getQuestionBankName())) {
               freemarkerData.getQuestionBankName().add(questionData.getQuestionBankName());
            }
            freemarkerData.setSingleChoiceNum(freemarkerData.getSingleChoiceNum()+1);
            //拼接questionData.getNum()+，
            if (freemarkerData.getSingleChoiceNumStr() == null) {
                freemarkerData.setSingleChoiceNumStr(questionData.getNum() + ",");
            } else {
                freemarkerData.setSingleChoiceNumStr(freemarkerData.getSingleChoiceNumStr() + questionData.getNum() + ",");
            }

            log.info("freemarkerData.getSingleChoiceNum():{}", freemarkerData.getSingleChoiceNum());
        }
        log.info("freemarkerData:{}", freemarkerData.getSingleChoiceNumStr());
    }
    //把对象转换成map
    public static Map<String, Object> ObjectToMap(Object obj) throws IllegalAccessException {
        Map<String, Object> dataMap = new HashMap<>();

        // 使用Java反射获取所有字段（包括私有字段）
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true); // 设置为可访问，即使是私有字段
            dataMap.put(field.getName(), field.get(obj)); // 获取字段值并放入map中
        }

        return dataMap;
    }

    private WordUtil() {
        throw new AssertionError();
    }

    /**
     * 导出excel
     *
     * @param request  请求对象
     * @param response 响应对象
     * @param map      word文档中参数
     * @param wordName 为模板的名字  例如xxx.ftl
     * @param fileName 是word 文件的名字 格式为："xxxx.doc"
     * @param name     是临时的文件夹米名称 string类型 可随意定义
     * @throws IOException
     */
    public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map, String wordName, String fileName, String name) throws IOException {
        Template freemarkerTemplate = configuration.getTemplate(wordName,"utf-8");
        File file = null;
        InputStream fin = null;
        ServletOutputStream out = null;
        FileInputStream fileInputStream = null;
        OutputStream outputStream1 = null;
        try {
            // 调用工具类的createDoc方法生成Word文档
            file = createDoc(map, freemarkerTemplate, name);
//            //保存文件file
//            // 保存word到本地
//            //resultPath生成一个临时文件夹，用于存放生成的word文档
            log.info("file:{}", resultPath);


            File localFile = new File(resultPath + fileName);
            if (!localFile.exists()) {
                localFile.createNewFile();
            }
            FileInputStream inputStream = new FileInputStream(file);
            FileOutputStream outputStream = new FileOutputStream(localFile);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) > 0) {
                outputStream.write(buffer, 0, length);
            }
            inputStream.close();
            outputStream.close();
            System.out.println("Word文档已保存到: " + localFile.getAbsolutePath());

//
//
//            System.out.println("File saved at: " + file.getAbsolutePath());
//            fin = new FileInputStream(file);
//            response.setCharacterEncoding("utf-8");
//            response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
//            fileName = new String(fileName.getBytes(), "ISO-8859-1");
//            response.setHeader("Content-Disposition", "attachment;filename=".concat(fileName));
//            out = response.getOutputStream();
//            byte[] buffer1 = new byte[1024];// 缓冲区
//            int bytesToRead = -1;
//            // 通过循环将读入的Word文件的内容输出到浏览器中
//            while ((bytesToRead = fin.read(buffer1)) != -1) {
//                out.write(buffer1, 0, bytesToRead);
//            }
        } finally {
            if (fin != null) {
                fin.close();
            }
            if (out != null) {
                out.close();
            }
            if (file != null) {
//                file.delete();// 删除临时文件
            }
        }
    }

    /**
     * 生成word文件
     * @param dataMap
     * @param template
     * @param name
     * @return
     */
    private static File createDoc(Map<?, ?> dataMap, Template template, String name) {

        File f = new File(name);
        Template t = template;
        try {
            // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
            Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
            t.process(dataMap, w);
            w.flush();
            w.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new ServiceException(ServiceCode.OPERATION_FAILED, "生成word文档失败");
        }
        //打印文件名称
        log.info("Word文档已保存到: ", name);



        return f;
    }




}

